/**
 * Vue的特点，如果是对象会使用Object.defineProperty定义响应式
 * 如果是数组会把数组的方法重写
 */
const obj = {
  name: 'aicherish',
  location: {
    x: 100,
    y: 200
  },
  arr: [1, 2, 3]
}

const methods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse']
const arrayProto = Array.prototype
const proto = Object.create(arrayProto)

methods.forEach((method) => {
  proto[method] = function () {
    arrayProto[method].call(this, ...arguments)
    render()
  }
})

function observer(obj) {
  if (Array.isArray(obj)) {
    obj.__proto__ = proto
    return
  }
  if (typeof obj === 'object') {
    Object.keys(obj).forEach((key) => {
      defineReactive(obj, key, obj[key])
    })
  }
}

function defineReactive(obj, key, value) {
  observer(value)

  Object.defineProperty(obj, key, {
    get() {
      return value
    },
    set(newVal) {
      observer(newVal)

      if (newVal === value) return
      value = newVal
      render()
    }
  })
}

function render() {
  console.log('视图渲染')
}

observer(obj)

// obj.name = 'aicherish'
// obj.location = {
//   z: 100
// }

// obj.location.z = 300

function $set(data, key, value) {
  if (Array.isArray(data)) {
    data.splice(key, 1, value)
    return
  }
  defineReactive(data, key, value)
}

// $set(obj, 'age', 24)
// obj.age = 25

// console.log(obj)

// obj.arr.push(7)
$set(obj.arr, 0, 100)
/**
 * Vue2.x不支持数组长度的变化、不支持通过索引改变数组
 * obj.arr[0] = 100
 */
console.log(obj.arr)
